#ifndef CPU_INSTR_H
#define CPU_INSTR_H
#include "types.h"
static inline void nop(void) {
    __asm__ __volatile__("nop");
}
static inline void cli(void) {
    __asm__ __volatile__("cli");
}
static inline void sti(void) {
    __asm__ __volatile__("sti");
}
static inline uint16_t inw(uint16_t port) {
    uint16_t data;
    //inb ax,dx
    __asm__ __volatile__("inw %1, %0" : "=a"(data) : "d"(port));
    return data;
}
static inline uint8_t inb(uint16_t port) {
    uint8_t data;
    //inb al,dx
    __asm__ __volatile__("inb %1, %0" : "=a"(data) : "d"(port));
    return data;
}
static inline void outb(uint16_t port, uint8_t data) {
    //outb al,dx
    __asm__ __volatile__("outb %0, %1" : : "a"(data), "d"(port));
}
static inline void outw(uint16_t port, uint16_t data) {
    //outb al,dx
    __asm__ __volatile__("out %0, %1" : : "a"(data), "d"(port));
}
//LGDT指令需要一个内存操作数，该操作数指向一个6字节的数据结构：
//前2字节是GDT的大小限制(limit)
//后4字节是GDT的线性基地址(base)
static inline void lgdt(uint32_t start, uint32_t size){
    struct __attribute__((packed)){
        uint16_t limit;
        uint16_t base_low;
        uint16_t base_high;
    }gdtr;
    gdtr.limit = size - 1;
    gdtr.base_low = start & 0xFFFF;
    gdtr.base_high = start >> 16;
    __asm__ __volatile__("lgdt %0" : : "m"(gdtr));
}
static inline void lidt(uint32_t start, uint32_t size){
    struct __attribute__((packed)){
        uint16_t limit;
        uint16_t base_low;
        uint16_t base_high;
    }idtr;
    idtr.limit = size - 1;
    idtr.base_low = start & 0xFFFF;
    idtr.base_high = start >> 16;
    __asm__ __volatile__("lidt %0" : : "m"(idtr));
}
static inline uint32_t read_cr0(void){
    uint32_t cr0;
    __asm__ __volatile__("mov %%cr0, %0" : "=r"(cr0));
    return cr0;
}
static inline void write_cr0(uint32_t cr0){
    __asm__ __volatile__("mov %0,%%cr0"::"r"(cr0));
}
static inline void far_jump(uint32_t selector,uint32_t offset){
    uint32_t addr[]={offset,selector};
    __asm__ __volatile__("ljmpl *(%[a])"::[a]"r"(addr));
}
static inline void hlt(void){
    __asm__ __volatile__("hlt");
}
static inline void ltr(uint16_t tss_sel){
    __asm__ __volatile__("ltr %%ax"::"a"(tss_sel));
}
static inline uint32_t read_eflags(void){
    uint32_t eflags;
    __asm__ __volatile__("pushfl; popl %0" : "=r"(eflags));
    return eflags;  
}
static inline void write_eflags(uint32_t eflags){
    __asm__ __volatile__("pushl %0; popfl"::"r"(eflags));
}
static inline uint32_t read_cr2(void){
    uint32_t cr2;
    __asm__ __volatile__("mov %%cr2,%0":"=r"(cr2));
    return cr2;
}
static inline uint32_t read_cr3(void){
    uint32_t cr3;
    __asm__ __volatile__("mov %%cr3,%0":"=r"(cr3));
    return cr3;
}
static inline void write_cr3(uint32_t cr3){
    __asm__ __volatile__("mov %0,%%cr3"::"r"(cr3));
}
static inline uint32_t read_cr4(void){
    uint32_t cr4;
    __asm__ __volatile__("mov %%cr4,%0":"=r"(cr4));
    return cr4;
}
static inline void write_cr4(uint32_t cr4){
    __asm__ __volatile__("mov %0,%%cr4"::"r"(cr4));
}
#endif